package ar.uba.fi.tp2Unit.displayers;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.HashMap;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

import ar.uba.fi.tp2Unit.displayers.gui.PieChart;
import ar.uba.fi.tp2Unit.framework.TestResult;
import ar.uba.fi.tp2Unit.framework.TestResultDisplayable;

/**
 * It displays the results of the execution of a test fixture 
 * in a graphic user interface.
 * 
 * @author grupo12
 * @see {@link TestResultDisplayable}, {@link PieChart}
 */
public class GUITestResultDisplayer implements TestResultDisplayable {

	private static final Color TEST_SUCCESS_COLOR = new Color(10, 139, 78);
	private static final Color TEST_FAIL_COLOR = new Color(222, 71, 67);
	private static final Color TEST_ERROR_COLOR = new Color(27, 75, 140);
	private static final String WINDOW_TITLE = new String("Test Result");
	private static final int WINDOW_WIDTH = 1024;
	private static final int WINDOW_HEIGHT = 250;
	private static final int RESULT_DETAIL_PANEL_BORDER_SPACE = 20;
	private static final int PIE_CHART_PANEL_BORDER_SPACE = 30;
	private static final int PIE_CHART_PANEL_WIDTH = 130;
	private static final int PIE_CHART_PANEL_HEIGHT = 130;
	private static final int SPLIT_PANE_DIVIDER_POSITION = 195;
	private static final String TITLE_FONT = new String("Calibri");
	private static final int TITLE_FONT_SIZE = 20;
	private static final String MESSAGE_FONT = new String("Courier New");
	private static final int MESSAGE_FONT_SIZE = 15;

	public void display(TestResult testResult) {

		JFrame testResultWindowFrame = getTestResultWindowFrame();
		JPanel resultDetailPanel = getJPanel(RESULT_DETAIL_PANEL_BORDER_SPACE);
		JPanel pieChartPanel = getJPanel(PIE_CHART_PANEL_BORDER_SPACE);
		JScrollPane resultDetailPanelScrollPane = new JScrollPane(
				resultDetailPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
				JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		JSplitPane horizontalSplitPane = getHorizontalSplitPane(pieChartPanel,
				resultDetailPanelScrollPane, SPLIT_PANE_DIVIDER_POSITION);

		addPieChartToPieChartPanel(testResult, pieChartPanel);
		addTestDetailToResultDetailPanel(testResult, resultDetailPanel);

		testResultWindowFrame.add(horizontalSplitPane);
		testResultWindowFrame.setVisible(true);
	}

	private JFrame getTestResultWindowFrame() {
		JFrame frame = new JFrame(WINDOW_TITLE);
		frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		return frame;
	}

	private JPanel getJPanel(int borderSpace) {
		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
		panel.setBorder(BorderFactory.createEmptyBorder(borderSpace,
				borderSpace, borderSpace, borderSpace));
		return panel;
	}

	private JSplitPane getHorizontalSplitPane(Component leftComponent,
			Component rightComponent, int dividerPosition) {
		JSplitPane horizontalSplitPane = new JSplitPane(
				JSplitPane.HORIZONTAL_SPLIT);
		horizontalSplitPane.setDividerLocation(dividerPosition);
		horizontalSplitPane.setLeftComponent(leftComponent);
		horizontalSplitPane.setRightComponent(rightComponent);
		return horizontalSplitPane;
	}

	private void addTestDetailToResultDetailPanel(TestResult testResult,
			JPanel resultDetailPanel) {
		addRunTestDetail(testResult, resultDetailPanel);
		addSuccededTestDetail(testResult, resultDetailPanel);
		addFailedTestDetail(testResult, resultDetailPanel);
		addErrorTestDetail(testResult, resultDetailPanel);
	}

	private void addErrorTestDetail(TestResult testResult,
			JPanel resultDetailPanel) {
		JLabel errorTest = getTitleJLabel("TEST ERRONEOS: "
				+ testResult.getErrorTests());
		errorTest.setForeground(TEST_ERROR_COLOR);
		resultDetailPanel.add(errorTest);
		for (String description : testResult.getErrors()) {
			JLabel errorDescription = getMessageJLabel("  " + description);
			resultDetailPanel.add(errorDescription);
		}
	}

	private void addFailedTestDetail(TestResult testResult,
			JPanel resultDetailPanel) {
		JLabel failedTest = getTitleJLabel("TEST FALLIDOS: "
				+ testResult.getFailedTests());
		failedTest.setForeground(TEST_FAIL_COLOR);
		resultDetailPanel.add(failedTest);
		for (String description : testResult.getFails()) {
			JLabel failDescription = getMessageJLabel("  " + description);
			resultDetailPanel.add(failDescription);
		}
	}

	private void addSuccededTestDetail(TestResult testResult,
			JPanel resultDetailPanel) {
		JLabel succeededTest = getTitleJLabel("TEST EXITOSOS: "
				+ testResult.getSuccessfulTests());
		succeededTest.setForeground(TEST_SUCCESS_COLOR);
		resultDetailPanel.add(succeededTest);
		for (String description : testResult.getOKs()) {
			JLabel succeedDescription = getMessageJLabel("  " + description);
			resultDetailPanel.add(succeedDescription);
		}
	}

	private void addRunTestDetail(TestResult testResult,
			JPanel resultDetailPanel) {
		JLabel runTests = getTitleJLabel(testResult.getRunTests()
				+ " TEST EJECUTADOS ");
		resultDetailPanel.add(runTests);		
		resultDetailPanel.add(new JLabel("Tiempo transcurrido: " + testResult.getElapsedTime() + " segs"));
		panelAddEmptyLine(resultDetailPanel);
	}

	private void panelAddEmptyLine(JPanel panel) {
		panel.add(new JLabel("\n"));		
	}

	private PieChart getPieChart(TestResult testResult) {
		Map<Color, Integer> slices = loadSlices(testResult);
		PieChart pieChart = new PieChart(slices, PIE_CHART_PANEL_WIDTH,
				PIE_CHART_PANEL_HEIGHT);
		return pieChart;
	}

	private Map<Color, Integer> loadSlices(TestResult testResult) {
		Map<Color, Integer> slices = new HashMap<Color, Integer>();
		slices.put(TEST_SUCCESS_COLOR, testResult.getSuccessfulTests());
		slices.put(TEST_FAIL_COLOR, testResult.getFailedTests());
		slices.put(TEST_ERROR_COLOR, testResult.getErrorTests());
		return slices;
	}

	private JLabel getTitleJLabel(String message) {
		JLabel label = new JLabel(message);
		label.setFont(new Font(TITLE_FONT, Font.BOLD, TITLE_FONT_SIZE));
		return label;
	}

	private JLabel getMessageJLabel(String message) {
		JLabel label = new JLabel(message);
		label.setFont(new Font(MESSAGE_FONT, Font.PLAIN, MESSAGE_FONT_SIZE));
		return label;
	}

	private void addPieChartToPieChartPanel(TestResult testResult,
			JPanel pieChartPanel) {
		PieChart pieChart = getPieChart(testResult);
		pieChartPanel.add(pieChart);
	}

}